//
//  TouchToken.m
//  GestIT
//
//  Created by Davide Spano on 27/08/12.
//  Copyright (c) 2012 Davide Spano. All rights reserved.
//

#import "TouchToken.h"
#import "TouchPoint.h"
#import "TouchEventArgs.h"

@implementation TouchToken

- (id) init{
    return [self initWithTrackingCount:StartLast :10];
}

- (id) initWithTracking:(PointTracking)tracking{
    return [self initWithTrackingCount:tracking :10];

}

- (id) initWithTrackingCount:(PointTracking)track :(int)c{
    self = [super init];
    if(self){
        self.tracking = track;
        touchCount = c;
        
        touches = [[NSMutableArray alloc] initWithCapacity:touchCount];
        for(int i = 0; i< touchCount; i ++){
            switch (self.tracking) {
                case Last:{
                    NSMutableArray* toAdd = [[NSMutableArray alloc] initWithCapacity:1];
                    [toAdd addObject:[[TouchPoint alloc]init]];
                    [touches addObject:toAdd];
                }break;
                    
                case Path:{
                    NSMutableArray* toAdd = [[NSMutableArray alloc] init];
                    [touches addObject:toAdd];
                }break;
                    
                case Previous:
                case StartLast:{
                    NSMutableArray* toAdd = [[NSMutableArray alloc] initWithCapacity:2];
                    [toAdd addObject:[[TouchPoint alloc]init]];
                    [toAdd addObject:[[TouchPoint alloc]init]];
                    [touches addObject:toAdd];
                }break;
                    
                case StartPrevious:{
                    NSMutableArray* toAdd = [[NSMutableArray alloc] initWithCapacity:3];
                    [toAdd addObject:[[TouchPoint alloc]init]];
                    [toAdd addObject:[[TouchPoint alloc]init]];
                    [toAdd addObject:[[TouchPoint alloc]init]];
                    [touches addObject:toAdd];
                }
                    
                default:
                    break;
            }
        }
    }
    return self;
}

- (void) save:(TouchEventArgs *)args{
    if(args.Id < 0 || args.Id >= touches.count){
        return;
    }
    int tid = args.Id;
    switch(self.tracking){
        case Last:{
            TouchPoint* zero = [[touches objectAtIndex:tid] objectAtIndex:0];
            zero.x = args.point.x;
            zero.y = args.point.y;
        }break;
            
        case Path:{
            [[touches objectAtIndex:tid] addObject:[[TouchPoint alloc] initWithPoint:args.point.x :args.point.y]];
        }break;
            	
        case Previous:{
            TouchPoint* zero = [[touches objectAtIndex:tid] objectAtIndex:0];
            TouchPoint* one = [[touches objectAtIndex:tid] objectAtIndex:1];
            zero.x = one.x;
            zero.y = one.y;
            one.x = args.point.x;
            one.y = args.point.y;
        }break;
            
        case StartLast:{
            TouchPoint* zero = [[touches objectAtIndex:tid] objectAtIndex:0];
            TouchPoint* one = [[touches objectAtIndex:tid] objectAtIndex:1];
            if(args.type == Start){
                zero.x = args.point.x;
                zero.y = args.point.y;
            }
            
            one.x = args.point.x;
            one.y = args.point.y;
        }break;
            
        case StartPrevious:{
            TouchPoint* zero = [[touches objectAtIndex:tid] objectAtIndex:0];
            TouchPoint* one = [[touches objectAtIndex:tid] objectAtIndex:1];
            TouchPoint* two = [[touches objectAtIndex:tid] objectAtIndex:2];
            
            if(args.type == Start){
                zero.x = args.point.x;
                zero.y = args.point.y;
            }
            
            one.x = two.x;
            one.y = two.y;
            
            two.x = args.point.x;
            two.y = args.point.y;
        }break;
            
    }
}

- (TouchPoint*) getPosition:(int) tid;{
    if(tid < 0 || tid >= touches.count){
        return [TouchPoint getErrorPoint];
    }
    
    switch(self.tracking){
        case Last:{
            return [[touches objectAtIndex:tid] objectAtIndex:0];
        }
            
        case StartLast:
        case Previous:{
            return [[touches objectAtIndex:tid] objectAtIndex:1];
        }
            
        case StartPrevious:{
            return [[touches objectAtIndex:tid] objectAtIndex:2];
        }
            
        case Path:{
            if([[touches objectAtIndex:tid] count] == 0){
                return [TouchPoint getErrorPoint];
            }else{
                NSMutableArray* touchHistory = [touches objectAtIndex:tid];
                return [touchHistory objectAtIndex:[touchHistory count] - 1];
            }
            
        }
    }
}

- (TouchPoint*) getPreviousPosition:(int)tid{
    if(tid < 0 || tid >= touches.count){
        return [TouchPoint getErrorPoint];
    }
    
    switch(self.tracking){
        case Previous:{
            return [[touches objectAtIndex:tid] objectAtIndex:0];
        }break;
            
        case StartPrevious:{
            return [[touches objectAtIndex:tid] objectAtIndex:1];
        }
            
        case Path:{
            if([[touches objectAtIndex:tid] count] <= 1){
                return [TouchPoint getErrorPoint];
            }else{
                NSMutableArray* touchHistory = [touches objectAtIndex:tid];
                return [touchHistory objectAtIndex:[touchHistory count] - 2];
            }
        }
            
        default:{
            return [TouchPoint getErrorPoint];
        }
    }
}

- (TouchPoint*) getStartPosition:(int)tid{
    if(tid < 0 || tid >= touches.count){
        return [TouchPoint getErrorPoint];
    }
    switch(self.tracking){
        case StartLast:
        case StartPrevious:
            return [[touches objectAtIndex:tid] objectAtIndex:0];
        case Path:{
            if([[touches objectAtIndex:tid] count] == 0){
                return [TouchPoint getErrorPoint];
            }else{
                return [[touches objectAtIndex:tid] objectAtIndex:0];
            }
        }
        default:{
            return [TouchPoint getErrorPoint];
        }
    }
}

- (TouchPoint*) getPositionAtTime:(int)tid :(int)i{
    if(tid > 0 || tid > touches.count){
        return [TouchPoint getErrorPoint];
    }
    if(self.tracking != Path){
        return [TouchPoint getErrorPoint];
    }
    
    if(i < 0 && i >= [[touches objectAtIndex:tid] count]){
        return [TouchPoint getErrorPoint];
    }
    
    return [[touches objectAtIndex:tid] objectAtIndex:i];
    
}

- (int) getPathLength:(int) tid{
    if(tid < 0 || tid >= touches.count){
        return -1;
    }
    
    if(self.tracking != Path){
        return -1;
    }
    
    return [[touches objectAtIndex:tid] count];
}


@end
